package linex

import (
	"fmt"
	"gitee.com/yehcnet/linex/conf"
	"net/http"
	"strings"
)

// 别名
type HandlerFunc func(*Context)

type RouterGroup struct {
	prefix      string        // 分组前缀
	middlewares []HandlerFunc // 中间件
	parent      *RouterGroup  // 父分组
	engine      *Engine       // 一个server唯一对应一个engine
}

type Engine struct {
	*RouterGroup
	router *router
	groups []*RouterGroup
}

// 新建一个无中间件的 linex server服务
func New() *Engine {
	engine := &Engine{
		router: newRouter(),
	}
	engine.RouterGroup = &RouterGroup{
		engine: engine,
	}
	engine.groups = []*RouterGroup{
		engine.RouterGroup,
	}
	return engine
}

// 新建一个使用默认中间件的 linex server服务
func Default() *Engine {
	engine := New()
	engine.Use(Logger(), Recovery())
	return engine
}

func (group *RouterGroup) Group(prefix string) *RouterGroup {
	engine := group.engine
	newGroup := &RouterGroup{
		prefix: prefix,
		parent: group,
		engine: engine,
	}
	engine.groups = append(engine.groups, newGroup)
	return newGroup
}

// 添加路由 get/post 的底层方法
func (group *RouterGroup) addRoute(method string, value string, handler HandlerFunc) {
	// 拼接 key 路由全转小写
	value = strings.ToLower(value)
	pattern := group.prefix + value
	group.engine.router.addRouter(method, pattern, handler)
}

// GET 方法
func (group *RouterGroup) GET(pattern string, handler HandlerFunc) {
	group.addRoute("GET", pattern, handler)
}

// POST 方法
func (group *RouterGroup) POST(pattern string, handler HandlerFunc) {
	group.addRoute("POST", pattern, handler)
}

// 添加中间件
func (group *RouterGroup) Use(middlewares ...HandlerFunc) {
	group.middlewares = append(group.middlewares, middlewares...)
}

// server 运行方法
func (e *Engine) Run(port ...int) error {
	var addr string
	if len(port) == 0 {
		addr = fmt.Sprintf("%s:%d", conf.GlobalObject.Host, conf.GlobalObject.Port)
	} else {
		addr = fmt.Sprintf("%s:%d", conf.GlobalObject.Host, port[0])
		conf.GlobalObject.Port = port[0]
	}
	return http.ListenAndServe(addr, e)
}

// 实现接口
func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
	var middlewares []HandlerFunc
	for _, group := range e.groups {
		// 前缀判断是否符合该组路由
		if strings.HasPrefix(req.URL.Path, group.prefix) {
			middlewares = append(middlewares, group.middlewares...)
		}
	}
	c := NewContext(w, req)
	c.handlers = middlewares
	e.router.handle(c)
}
